package com.ll.agent.ASMStudy.demo1;

/**
 * @description:
 * @author: LiuLei
 * @create: 2024-07-19
 **/
import com.ll.agent.ASMStudy.generate.ASMGenerator;
import org.objectweb.asm.*;
import org.objectweb.asm.commons.AdviceAdapter;

import java.io.FileOutputStream;

public class ModifyMethodExample {
    public static void main(String[] args) throws Exception {
        ClassReader classReader = new ClassReader("com/ll/agent/ASMStudy/demo1/ExampleClass");
        ClassWriter classWriter = new ClassWriter(classReader, 0);

        classReader.accept(new ClassVisitor(Opcodes.ASM9, classWriter) {
            @Override
            public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
                MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
                if ("myMethod121212".equals(name)){
//                    return new ModifySingleParamAdviceAdapter(Opcodes.ASM9, mv, access, name, descriptor);
                }
                if ("myMethod1".equals(name) ) {
                    return new ModifySingleParamAdviceAdapter(Opcodes.ASM9, mv, access, name, descriptor);
                }
                if ("myMethod2".equals(name)) {
                    return new ModifySingleParamAdviceAdapter(Opcodes.ASM9, mv, access, name, descriptor);
                }
                if ("myMethod3".equals(name) ) {
                    return new ModifySingleParamAdviceAdapter(Opcodes.ASM9, mv, access, name, descriptor);
                }
                if ("myMethod".equals(name) ) {
                    return new ModifySingleParamAdviceAdapter(Opcodes.ASM9, mv, access, name, descriptor);
                }
                if ("myMethod4".equals(name) ) {
                    return new ModifySingleParamAdviceAdapter(Opcodes.ASM9, mv, access, name, descriptor);
                }
                return mv;
            }
        }, 0);

        byte[] modifiedClass = classWriter.toByteArray();

//        Class<?> generatedClass = new ASMGenerator.MyClassLoader().defineClass(CLASS_NAME, modifiedClass);

        try (FileOutputStream fos = new FileOutputStream("./ExampleClass.class")) {
            fos.write(modifiedClass);
        }
    }

    private static class ModifySingleParamAdviceAdapter extends AdviceAdapter {
        protected ModifySingleParamAdviceAdapter(int api, MethodVisitor methodVisitor, int access, String name, String descriptor) {
            super(api, methodVisitor, access, name, descriptor);
        }

        @Override
        protected void onMethodEnter() {
            mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
            mv.visitLdcInsn("Method with single parameter called");
            mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
        }
    }
}

